package com.breeze.breezelive.play;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.SystemClock;
import android.util.Log;
import android.view.Surface;

import java.io.IOException;
import java.nio.ByteBuffer;

public class VideoPlayerThread extends Thread {
    private static final String TAG = "VideoPlayerThread";
    private static final int TIMEOUT_MS = 12000;
    private Surface mSurface;
    private MediaCodec mMediaCodec;
    private MediaCodec.BufferInfo mBufferInfo;
    private MediaExtractor mExtractor;
    private String mPath;
    private int mWidth, mHeight;
    private int mFrameRate;

    public VideoPlayerThread(String path) {
        this.mWidth = 0;
        this.mHeight = 0;
        this.mSurface = null;
        this.mPath = path;
    }

    public void setVideoSize(int mWidth, int mHeight) {
        this.mWidth = mWidth;
        this.mHeight = mHeight;
    }

    public void setSurface(Surface surface) {
        this.mSurface = surface;
    }

    public boolean prepare() {
        if (mSurface == null || mWidth == 0 || mHeight == 0) {
            Log.e(TAG, "prepare failed");
            return false;
        }
        try {
            mBufferInfo = new MediaCodec.BufferInfo();
            mExtractor = new MediaExtractor();
            mExtractor.setDataSource(mPath);
            MediaFormat mediaFormat = null;
            for (int i = 0; i < mExtractor.getTrackCount(); i++) {
                mediaFormat = mExtractor.getTrackFormat(i);
                String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith(MediaFormat.MIMETYPE_VIDEO_AVC)) {
                    mExtractor.selectTrack(i);
                    break;
                }
            }
            mFrameRate = mediaFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
            Log.i(TAG, "prepare: frameRate=" + mFrameRate);
            mMediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
            mMediaCodec.configure(mediaFormat, mSurface, null, 0);
            mMediaCodec.start();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public void run() {
        long startMs = System.currentTimeMillis();
        int index = 0;
        while (true) {
            int inputIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_MS);
            if (inputIndex < 0) {
                Log.e(TAG, "decode failed");
                break;
            }

            ByteBuffer inputBuffer = mMediaCodec.getInputBuffer(inputIndex);
            inputBuffer.clear();
            int sampleSize = mExtractor.readSampleData(inputBuffer, 0);
            if (sampleSize <= 0) {
                break;
            }
            long pts = getPts(index++, mFrameRate);
            mMediaCodec.queueInputBuffer(inputIndex, 0, sampleSize, pts, 0);
            int outputIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_MS);
            while (outputIndex > 0) {
                Log.i(TAG, "run input pts=" + pts + ", output pts=" + mBufferInfo.presentationTimeUs);
                // 帧控制
                while (mBufferInfo.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
                    SystemClock.sleep(50);
                }
                mMediaCodec.releaseOutputBuffer(outputIndex, true);
                outputIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_MS);
            }
            if (!mExtractor.advance()) {
                break;
            }
        }
        release();
    }

    private long getPts(int index, int frameRate) {
        return index * 1000000 / frameRate;
    }

    private void release() {
        try {
            mExtractor.release();
            mExtractor = null;
            mMediaCodec.stop();
            mMediaCodec.release();
            mMediaCodec = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}